﻿using System.Diagnostics.CodeAnalysis;

namespace DimensionsHelper.LanguageService.Syntax;

/// <summary>
///     表达式的基类
/// </summary>
public abstract class Expression : SyntaxNode
{
    private SyntaxToken? _leftParenthesisToken;
    private SyntaxToken? _rightParenthesisToken;

    protected internal Expression(SyntaxKinds kind, SyntaxNode? parent) :
        base(kind, parent)
    {
    }


    /// <summary>
    ///     左括号
    /// </summary>
    public SyntaxToken? LeftParenthesisToken => _leftParenthesisToken;

    /// <summary>
    ///     右括号
    /// </summary>
    public SyntaxToken? RightParenthesisToken => _rightParenthesisToken;


    /// <summary>
    ///     判断此表达式是否是空表达式
    /// </summary>
    public override bool IsEmpty => Kind == SyntaxKinds.EmptyExpression;


    public Expression Update(SyntaxToken? leftParenthesisToken, SyntaxToken? rightParenthesisToken)
    {
        SetChildNullableField(ref _leftParenthesisToken, SyntaxToken.IsNullOrEmpty, leftParenthesisToken);
        SetChildNullableField(ref _rightParenthesisToken, SyntaxToken.IsNullOrEmpty, rightParenthesisToken);
        return this;
    }


    public static bool IsEmptyExpression([NotNullWhen(false)] Expression? expression)
    {
        return expression == null || expression.IsEmpty;
    }


    public static bool IsConstantExpression(Expression expression)
    {
        return expression.IsOneOfNode(SyntaxKinds.String,
            SyntaxKinds.Integer, SyntaxKinds.Double, SyntaxKinds.Boolean,
            SyntaxKinds.Categorical);
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, LeftParenthesisToken, RightParenthesisToken);
        base.AcceptVisitor(visitor);
    }
}


public static partial class NodeConverter
{
    public static StringLiteral ToString(Expression expression)
    {
        if (expression.IsNode(SyntaxKinds.String))
        {
            return (StringLiteral)expression;
        }

        StringLiteral literal = NodeFactory.CreateStringLiteral(null, false, expression.Text);
        literal.UpdateFrom(expression);
        return literal;
    }


    /// <summary>
    ///     将指定节点转换为整数类型，并使用给定的数值。
    ///     此方法不会检查表达式的具体内容，原始表达式的基础属性也将复制到新的节点上。
    /// </summary>
    /// <param name="expression">原始表达式</param>
    /// <param name="value">转换后的数值</param>
    public static IntegerLiteral ToInteger(Expression expression, int value)
    {
        IntegerLiteral literal = NodeFactory.CreateIntegerLiteral(null, value);
        literal.UpdateFrom(expression);
        return literal;
    }


    /// <summary>
    ///     将指定节点转换为浮点数类型，并使用给定的数值。
    ///     此方法不会检查表达式的具体内容，原始表达式的基础属性也将复制到新的节点上。
    /// </summary>
    /// <param name="expression">原始表达式</param>
    /// <param name="value">转换后的数值</param>
    public static DoubleLiteral ToDouble(Expression expression, double value)
    {
        DoubleLiteral literal = NodeFactory.CreateDoubleLiteral(null, value);
        literal.UpdateFrom(expression);
        return literal;
    }


    /// <summary>
    ///     将指定节点转换为布尔值类型，并使用给定的数值。
    ///     此方法不会检查表达式的具体内容，原始表达式的基础属性也将复制到新的节点上。
    /// </summary>
    /// <param name="expression">原始表达式</param>
    /// <param name="value">转换后的数值</param>
    public static BooleanLiteral ToBoolean(Expression expression, bool value)
    {
        BooleanLiteral literal = NodeFactory.CreateBooleanLiteral(null, value);
        literal.UpdateFrom(expression);
        return literal;
    }


    /// <summary>
    ///     使用给定的表达式创建一个空的分类常量表达式。
    ///     此方法不会检查表达式的具体内容，原始表达式的基础属性也将复制到新的节点上。
    /// </summary>
    /// <param name="expression">原始表达式</param>
    public static CategoricalLiteral ToCategorical(Expression expression)
    {
        CategoricalLiteral literal = NodeFactory.CreateCategoricalLiteral(null,
            null,
            null,
            Array.Empty<CategoryLiteral>());
        literal.UpdateFrom(expression);
        return literal;
    }
}